from flask import request, jsonify
from aps import app

from aps.models.fase import *
from aps.models.fasetipoitem import *
from aps.models.faserol import *
from aps.models.usuario import *
from aps.models.proyecto import *
from aps.models.proyectofase import *
from aps.models.rol import *
from aps.models.tipoitem import *
from aps.models.item import *
from aps.models.tipoitematributo import *

@app.route('/crear_fase', methods=['GET', 'POST'])  
def crear_fase():
    """
    Nos permite traer los parametros que fueron cargados por el usuario
    y guardarlos en la base de datos.
    @param request: objeto que encapsula la peticion del servidor
    @return: True si la accion se realizo correctamente
    """
    nombre          = request.form['nombre']
    descripcion     = request.form['descripcion']
    fechainicio     = request.form['fechainicio']
    fechafin        = request.form['fechafin']
    observaciones   = request.form['observaciones']
    estado          = 'NO-INICIADO'
    
    # Id del proyecto a asignar fases
    id_proyecto     = request.form['id_proyecto']
    model           = Fase(nombre, descripcion, fechainicio, fechafin, observaciones, estado)
    bdsession.add(model)    
    bdsession.flush()
    id_fase = model.id
    
    # Fase y proyecto que vamos a relacionar obtenemos de la BD  
    proyecto        = bdsession.query(Proyecto).filter_by(id=id_proyecto).first()
    proyecto.nfases = proyecto.nfases + 1
    orden           = proyecto.nfases
    proyecto.fases.append(ProyectoFase(id_proyecto,id_fase, orden))
    
    # Habilitamos el rol de lider dentro de la fase
    model.roles.append(FaseRol(id_fase,2))
    bdsession.merge(model)
    
    # Guardamos los cambios
    bdsession.merge(proyecto)  
    
    return jsonify ({'success' : True})

@app.route('/modificar_fase', methods=['GET', 'POST'])  
def modificar_fase():
    """
    Nos permite traer los parametros que fueron modificados por el usuario
    y guardar los cambios en la base de datos.
    @param request: objeto que encapsula la peticion del cliente
    @return: True si la accion se realizo correctamente
    """ 
    
    id            = request.form['id']
    nombre        = request.form['nombre']
    descripcion   = request.form['descripcion']
    fechainicio   = request.form['fechainicio']
    fechafin      = request.form['fechafin']
    observaciones = request.form['observaciones']
    fase          = bdsession.query(Fase).filter_by(id=id).first()
    estado        = fase.estado
    
    # se modifica en la BD
    model         = Fase(nombre, descripcion, fechainicio, fechafin, observaciones, estado)
    model.id      = id
    bdsession.merge(model)   
    return jsonify ({'success' : True})

@app.route('/eliminar_fase', methods=['GET', 'POST'])  
def eliminar_fase():
    """
    Nos permite traer el id de la fase a eliminar, eliminar las dependendcias
    de la misma con respecto a otras tablas y eliminar el registro de la base de datos.
    @param request: objeto que encapsula la peticion del cliente
    @return: True si la accion se realizo correctamente y False en caso contrario
    """    
    id_proyecto   = request.form['id_proyecto']
    id            = request.form['id']
    fase          = bdsession.query(Fase).filter_by(id=id).first()
    
    if fase is None:
        return jsonify ({'success':False})
    
    # Actualizamos el numero de fases dentro del proyecto
    proyecto        = bdsession.query(Proyecto).filter_by(id=id_proyecto).first()
    proyecto.nfases = proyecto.nfases-1
    bdsession.merge(proyecto)
    
    # Actualizamos el orden de las demas fases
    sentencia       = 'SELECT * from ProyectoFase WHERE idproyecto = {0} and orden > (SELECT orden from ProyectoFase WHERE idproyecto ={1} and idfase ={2})'.format(id_proyecto,id_proyecto,id)
    proyectofases   = bdsession.query(ProyectoFase).from_statement(sentencia).all()
    for f in proyectofases:
        f.orden = f.orden-1
        bdsession.merge(f)
 
    # Eliminamos la fase
    fase.eliminar_dependencias()
    bdsession.refresh(fase)
    bdsession.delete(fase)
    
    return jsonify ({'success' : True})

@app.route('/iniciar_fase', methods=['GET', 'POST'])  
def iniciar_fase():
    """
    Nos permite iniciar una fase siempre y cuando tenga al menos un item.
    @param request: objeto que encapsula la peticion del cliente
    @return: True si la accion se realizo correctamente y False en caso contrario
    """    
    id_fase = request.form['id_fase']
    fase = bdsession.query(Fase).filter_by(id=id_fase).first()
    sentencia = 'SELECT * from Item WHERE idfase={0}'.format(id_fase)
    items     = bdsession.query(Item).from_statement(sentencia).all()
    items = [ it for it in items if it.estado != u'ELIMINADO' ]
    if len(items) != 0:
        fase.estado = 'INICIADO'
        bdsession.merge(fase)
        return jsonify ({'success': True})
    else:
        return jsonify ({'success': False})
        
@app.route('/reordenar_fase', methods=['GET', 'POST'])  
def reordenar_fase():
    """
    Nos permite reordenar las fases de un proyecto.
    @param request: objeto que encapsula la peticion del cliente
    @return: True si la accion se realizo correctamente y False en caso contrario
    """    
    received      = eval(request.form['data'])
    id_proyecto   = received ['id_proyecto']
    idfases       = received ['idfases']
    orden         = received ['orden']
    for i in range(0,len(idfases)):
        sentencia = 'SELECT * from ProyectoFase WHERE idproyecto={0} and idfase={1}'.format(id_proyecto,idfases[i])
        proyectofase = bdsession.query(ProyectoFase).from_statement(sentencia).first()
        proyectofase.orden = orden[i]
        bdsession.merge(proyectofase)
    return jsonify ({'success': True})
        
@app.route('/terminar_fase', methods=['GET', 'POST'])  
def terminar_fase():
    """
    Nos permite terminar una fase siempre y cuando todos sus items esten bloqueados.
    @param request: objeto que encapsula la peticion del cliente
    @return: True si la accion se realizo correctamente y False en caso contrario
    """    
    id_fase = request.form['id_fase']
    
    fase = bdsession.query(Fase).filter_by(id=id_fase).first()
    proact = bdsession.query(ProyectoFase).filter_by(idfase=id_fase).first()
    pro = bdsession.query(ProyectoFase).filter_by(idproyecto=proact.idproyecto).all()
    
    for fa in pro:
        if fa.idfase != id_fase:
            faseO = bdsession.query(Fase).filter_by(id=fa.idfase).first()
            if fa.orden < proact.orden and faseO.estado == u'INICIADO':  
                return jsonify ({'success':False})   
                              
    sentencia = 'SELECT * from Item WHERE idfase={0}'.format(id_fase)
    items     = bdsession.query(Item).from_statement(sentencia).all()
    items = [ it for it in items if it.estado != u'ELIMINADO' ]
    lista   = items
    lista   = [ it for it in lista if it.estado == u'BLOQUEADO']
    if len(items) == len(lista) and len(items) != 0:
        fase.estado = 'FINALIZADO'
        bdsession.merge(fase)
        return jsonify ({'success':True})
    else:
        return jsonify ({'success':False})
          

@app.route('/consultar_fase', methods=['GET', 'POST'])  
def consultar_fase():
    """
    Nos permite traer los parametros de consulta(el filtro y el valor) y mostrar
    las fases que cumplen con la condicion del filtro.
    @param request: objeto que encapsula la peticion del cliente
    @return: True si la accion se realizo correctamente
    """ 
    fases = None 
    id_proyecto    = request.args['id_proyecto']
    if request.args.has_key('filtro'):     
        filtro         = request.args['filtro']
        valor          = request.args['valor']
        sentencia      = 'SELECT * from Fase WHERE id in (SELECT idfase from ProyectoFase WHERE idproyecto={0}) and {1}=\'{2}\''.format(id_proyecto, filtro,valor)
        fases  = bdsession.query(Fase).from_statement(sentencia).all()
    
    else:
        sentencia      = 'SELECT * from Fase WHERE id in (SELECT idfase from ProyectoFase WHERE idproyecto={0})'.format(id_proyecto)
        fases = bdsession.query(Fase).from_statement(sentencia).all()

    data = []
    for fase in fases:
        item = {}
        item['id'] = fase.id
        item['orden'] = bdsession.query(ProyectoFase).filter_by(idfase=fase.id).first().orden
        item['nombre'] = fase.nombre
        item['descripcion'] = fase.descripcion
        item['fechainicio'] = str(fase.fechainicio)
        item['fechafin'] = str(fase.fechafin)
        item['estado'] = fase.estado
        data.append(item)
    return jsonify ({'success':True, 'data':data, 'total':len(data)})
    
@app.route('/consultar_importar_fase', methods=['GET', 'POST'])  
def consultar_importar_fase():
    """
    Nos permite traer todas las fases de un proyecto
    @param request: objeto que encapsula la peticion del cliente
    @return: True si la accion se realizo correctamente
    """ 
    fases = None 
    id_proyecto    = request.args['id_proyecto']
    sentencia      = 'SELECT * from Fase WHERE id in (SELECT idfase from ProyectoFase WHERE idproyecto={0})'.format(id_proyecto)
    fases = bdsession.query(Fase).from_statement(sentencia).all()

    data = []
    for fase in fases:
        item = {}
        item['id'] = fase.id
        item['orden'] = bdsession.query(ProyectoFase).filter_by(idfase=fase.id).first().orden
        item['nombre'] = fase.nombre
        item['descripcion'] = fase.descripcion
        item['fechainicio'] = str(fase.fechainicio)
        item['fechafin'] = str(fase.fechafin)
        item['estado'] = fase.estado
        data.append(item)
    return jsonify ({'success':True, 'data':data, 'total':len(data)})    
    

@app.route('/llenar_combo_fase', methods=['GET', 'POST'])  
def llenar_combo_fase():
    id_proyecto = request.args['idproyecto']
    id_rol      = request.args['idrol']
    print id_proyecto
    print id_rol
    # Recuperamos los datos desde la BD
    proyecto    = bdsession.query(Proyecto).filter_by(id=id_proyecto).first()
    rol         = bdsession.query(Rol).filter_by(id=id_rol).first()
    
    # Procesamos la lista de fases con los roles habilitados
    data = []
    if rol.id == 2:
        for pf in proyecto.fases:
            id_roles = [ p.rol.id for p in pf.fase.roles ]
            item     = {}
            if rol.id in id_roles:
                item['idfase'] = pf.fase.id
                item['nombre'] = pf.fase.nombre
                item['estado'] = pf.fase.estado
                item['orden']  = pf.orden
                item['nombre_orden'] = '{0} ({1})'.format(pf.fase.nombre,pf.orden)
                data.append(item)
    elif rol.id == 3:
        for pf in proyecto.fases:
            item     = {}
            item['idfase'] = pf.fase.id
            item['nombre'] = pf.fase.nombre
            item['estado'] = pf.fase.estado
            item['orden']  = pf.orden
            item['nombre_orden'] = '{0} ({1})'.format(pf.fase.nombre,pf.orden)
            data.append(item)    
    else:
        for pf in proyecto.fases:
            id_roles = [ p.rol.id for p in pf.fase.roles if pf.fase.estado == u'INICIADO']
            item     = {}
            if rol.id in id_roles:
                item['idfase'] = pf.fase.id
                item['nombre'] = pf.fase.nombre
                item['estado'] = pf.fase.estado
                item['orden']  = pf.orden
                item['nombre_orden'] = '{0} ({1})'.format(pf.fase.nombre,pf.orden)
                data.append(item)
    # retornamos los datos
    return jsonify ({'success':True, 'total':len(data), 'data':data})

@app.route('/consulta_rol_x_fase', methods=['GET', 'POST'])  
def consulta_rol_x_fase():
    """
    Nos permite obtener la lista detallada de roles habilitados de una fase
    @param request: objeto que encapsula la peticion del cliente
    @return: True si la accion se realizo correctamente
    """
    id_fase = request.args['idfase']
    fase    = bdsession.query(Fase).filter_by(id=id_fase).first()
    data = []
    for rol in fase.roles:
        if rol.rol.id > 2:
            item = {}
            item['id']          = rol.rol.id
            item['nombre']      = rol.rol.nombre
            item['descripcion'] = rol.rol.descripcion
            data.append(item)
    return jsonify ({'success':True, 'data':data, 'total':len(data)})
    
@app.route('/importar_fase', methods=['GET', 'POST'])  
def importar_fase():
    """
    Nos permite importar una fase y sus tipo de items desde otro proyecto.
    @param request: objeto que encapsula la peticion del cliente
    @return: True si la accion se realizo correctamente
    """ 
    id_fase     = request.form['id_fase']
    id_proyecto = request.form['id_proyecto']
    fase        = bdsession.query(Fase).filter_by(id=id_fase).first() 
    model       = Fase(fase.nombre, fase.descripcion, '0001-01-01', '0001-01-01', fase.observaciones, 'NO-INICIADO')
    bdsession.add(model)  
    bdsession.flush()
    idfase     = model.id
    
    fase_rol = FaseRol(idfase, 2)
    bdsession.add(fase_rol)

    #Fase y proyecto que vamos a relacionar obtenemos de la BD  
    proyecto        = bdsession.query(Proyecto).filter_by(id=id_proyecto).first()
    proyecto.nfases = proyecto.nfases + 1
    orden           = proyecto.nfases
    proyecto.fases.append(ProyectoFase(id_proyecto,idfase, orden))
    # guardamos los cambios
    bdsession.merge(proyecto)
    
    # Relacionamos la fase nueva con los tipo de items de la fase del otro proyecto
    fasenueva= bdsession.query(Fase).filter_by(id=idfase).first()
    
    # clonamos cada tipo de item de la fase antigua
    for tipoitem in fase.tipoitems:
        model         = Tipoitem(tipoitem.tipoitem.nombre, tipoitem.tipoitem.descripcion, tipoitem.tipoitem.prefijo)
        bdsession.add(model)
        bdsession.flush()
        id_tipoitem = model.id 
        
        # agregamos a la fase nueva cada uno de los tipo de items clonados
        fasenueva.tipoitems.append(FaseTipoitem(idfase,id_tipoitem))
        
        #obtenemos el tipo de item viejo y el tipo de item clonado
        ti = bdsession.query(Tipoitem).filter_by(id=tipoitem.tipoitem.id).first()
        tin = bdsession.query(Tipoitem).filter_by(id=id_tipoitem).first()
        
        # relacionamos cada atributo del tipo de item viejo con el tipo de item clonado
        for atributo in ti.atributos:
            tin.atributos.append(TipoitemAtributo(id_tipoitem, atributo.atributo.id))
        bdsession.merge(tin)
    
    # guardamos los cambios
    bdsession.merge(fasenueva)
    
    return jsonify ({'success' : True})

@app.route('/consulta_fase_combo', methods=['GET', 'POST'])  
def consulta_fase_combo():
    """
    Nos permite obtener la lista de fases de un proyecto
    @param request: objeto que encapsula la peticion del cliente
    @return: True si la accion se realizo correctamente
    """
    if  not request.args.has_key('id_proyecto'):
        return jsonify ({'success':False, 'total':0, 'data':[]})
    
    id_proyecto = request.args['id_proyecto']
    proyectos   = None 
    sentencia   = 'SELECT * from Fase WHERE id in (SELECT idfase from ProyectoFase WHERE idproyecto={0})'.format(id_proyecto)
    fases = bdsession.query(Fase).from_statement(sentencia).all()
  
    data = []
    for fase in fases:
        item = {}
        item['id'] = fase.id
        item['nombre'] = fase.nombre
        data.append(item)
    return jsonify ({'total':len(data), 'data':data})
